/**
 * @file .
 * @author wangxiaowei0303@163.com
 */

#ifdef ENABLE_DEBUG
#include <stdio.h>
#endif
#include <stdlib.h>

#include <stdexcept>

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "Filter.h"
#include "../string_util.h"
#include "../opencv_util.h"

/*
 * ROW;为 this->row 参数呈现给用户的名称.
 * COL;为 this->col 参数呈现给用户的名称.
 */
#define ROW "row"
#define COL "col"

Filter::~Filter()
{
    ;
}

void
Filter::help(std::string &buf) const
{
    buf.append(
        ROW ";空间滤波器模板的行数;要求:奇数,默认值为 3.\n"
        COL ";空间滤波器模板的列数;要求:奇数,默认值为 3.\n"
    );
    return ;
}

/*
 * 处理不合法的参数名.
 * 这里'不合法的参数名'指的是当前算法不支持的参数.
 */
static void
handleInvalidArg(const char *fun,const char *arg)
{
    std::string err("ERROR;不合法的参数名;func: ");
    err += fun;
    err += ";argName: ";
    err += arg;
    err += ";\n";
    throw std::runtime_error(err);
}

/*
 * 处理不合法的参数值.表明在 func() 函数中,检测到参数 arg 的值 val 不合法.
 */
void
Filter::handleInvalidArgVal(const char *func,const char *arg,const char *val)
{
    std::string err("ERR;不合法的参数值;func: ");
    err += func;
    err += ";argName: ";
    err += arg;
    err += ";argVal: ";
    err += val;
    err += ";\n";
    throw std::runtime_error(err);
}

void
Filter::set(const char *argname,const char *argval)
{
    if (strEqual(argname,ROW)) {
        this->row = atoi(argval);
        if (this->row < 0 || !isOdd(this->row)) 
            handleInvalidArgVal(__PRETTY_FUNCTION__,argname,argval);
    } else if (strEqual(argname,COL)) {
        this->col = atoi(argval);
        if (this->col < 0 || !isOdd(this->col))
            handleInvalidArgVal(__PRETTY_FUNCTION__,argval,argval);
    } else 
        handleInvalidArg(__PRETTY_FUNCTION__,argname);
}

const char*
Filter::get(const char *argname,std::string &buf) const
{
    size_t oldsize = buf.size();
    if (strEqual(argname,ROW)) 
        addFormat(buf,"%d",this->row); 
    else if (strEqual(argname,COL)) 
        addFormat(buf,"%d",this->col);
    else
        return 0;
    return buf.data() + oldsize;
}

void
Filter::getSupportedArgs(std::vector<std::string> &arglist) const
{
    arglist.push_back(ROW);
    arglist.push_back(COL);
    return ;
}

cv::Mat
Filter::makeBorder(const cv::Mat &m,int &t,int &b,int &l,int &r)
{
    t = b = (this->row - 1) / 2;
    l = r = (this->col - 1) / 2;
    cv::Mat m1(m.rows + t + b,m.cols + r + l,CV_8UC1);
    cv::copyMakeBorder(m,m1,t,b,l,r,cv::BORDER_REPLICATE);
    return m1;
}

void
Filter::process(cv::Mat &m) 
{
    if (m.channels() != 1 || m.depth() != CV_8U) {
        std::string err;
        addFormat(err,
            "ERROR;Filter::process(): 不支持的图像格式;"
            "channels: %d(支持: 1);"
            "depth: %s(支持: CV_8U)\n",
            m.channels(),
            depth2str(m.depth()));
        throw std::runtime_error(err);    
    }
    
    int tadd,badd,ladd,radd;
    cv::Mat m1 = this->makeBorder(m,tadd,badd,ladd,radd);

    for (int r = tadd,rMax = tadd + m.rows; r < rMax; ++r) {
        for (int c = ladd,cMax = ladd + m.cols; c < cMax; ++c) {
            double tmp = operOnNeigh(m1(cv::Rect(c - ladd,r - tadd,col,row)));
            m.at<uchar>(r - tadd,c - ladd) = cv::saturate_cast<uchar>(tmp);
        } 
    }

    return ;
}




